#include "tcp.h"

Tcp::Tcp(void)
{
	Open();
}
Tcp::~Tcp(void)
{
}
bool Tcp::Open(void)
{
	if( -1 == m_fd )
	{
		m_fd = socket(AF_INET, SOCK_STREAM, 0);
	}
	return (-1 != m_fd);
}
bool Tcp::Bind(const string& ip, int port)
{
	struct sockaddr_in addr;

	if( -1 == m_fd || ip.empty() )
	{
		return false;
	}
	addr.sin_family = AF_INET;
	addr.sin_port = htons( port );
	addr.sin_addr.s_addr = htonl( inet_network(ip.data()) );

	int ret = bind(m_fd, (struct sockaddr*)&addr, (socklen_t)sizeof(addr));

	return (0 == ret);
}
bool Tcp::Connect(const string& ip, int port)
{
	struct sockaddr_in addr;

	if( -1 == m_fd || ip.empty() )
	{
		return false;
	}
	addr.sin_family = AF_INET;
	addr.sin_port = htons( port );
	addr.sin_addr.s_addr = htonl( inet_network(ip.data()) );

	int ret = connect(m_fd, (struct sockaddr*)&addr, (socklen_t)sizeof(addr));

	return (0 == ret);
}
bool Tcp::Listen(int backlog)
{
	if( -1 == m_fd )
	{
		return false;
	}
	int ret = listen(m_fd, backlog);

	return (0 == ret);
}
bool Tcp::Accept(Socket& sock)
{
	struct sockaddr_in addr;
	socklen_t len = sizeof(addr);

	int fd = accept(m_fd, (struct sockaddr*)&addr, &len);
	if( -1 == fd )
	{
		perror("accept");
		return false;
	}
	sock.Close();
	sock.SetSocket(fd);

	return true;
}
bool Tcp::GetSocketName(string& ip, int& port)
{
	struct sockaddr_in addr;
	socklen_t slen = sizeof(addr);

	int ret = getsockname(m_fd, (struct sockaddr*)&addr, &slen);
	if( 0 == ret )
	{
		ip = inet_ntoa(addr.sin_addr);
		port = ntohs(addr.sin_port);
	}
	return (0 == ret);
}
bool Tcp::GetPeerName(string& ip, int& port)
{
	struct sockaddr_in addr;
	socklen_t slen = sizeof(addr);

	int ret = getpeername(m_fd, (struct sockaddr*)&addr, &slen);
	if( 0 == ret )
	{
		ip = inet_ntoa(addr.sin_addr);
		port = ntohs(addr.sin_port);
	}
	return (0 == ret);
}
bool Tcp::GetSocketLevel(int option, void* buf, int& len)
{
	int ret = getsockopt(m_fd, SOL_SOCKET, option, buf, (socklen_t*)&len);

	return (0 == ret);
}
bool Tcp::SetSocketLevel(int option, const void* buf, int len)
{
	int ret = setsockopt(m_fd, SOL_SOCKET, option, buf, (socklen_t)len);

	return (0 == ret);
}
bool Tcp::GetTcpLevel(int option, void* buf, int& len)
{
	int ret = getsockopt(m_fd, SOL_TCP, option, buf, (socklen_t*)&len);

	return (0 == ret);
}
bool Tcp::SetTcpLevel(int option, const void* buf, int len)
{
	int ret = setsockopt(m_fd, SOL_TCP, option, buf, (socklen_t)len);

	return (0 == ret);
}
